/**
  ******************************************************************************
  * @file    Libraries/Device/TS32Fx/TS32Fx_LL_Driver/src/ts32fx_ll_gpio.c
  * @author  TOPSYS Application Team
  * @version V1.0.0
  * @date    02-11-2018
  * @brief   This file contains all the GPIO LL firmware functions.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2018 TOPSYS</center></h2>
  *
  *
  *
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "include.h"

/** @addtogroup TS32Fx_StdPeriph_Driver TS32Fx Driver
  * @{
  */
  
/** @defgroup gpio_interface_gr GPIO Driver
  * @ingroup  TS32Fx_StdPeriph_Driver
  * @{
  */

/** @addtogroup GPIO_LL_Driver GPIO LL Driver
  * @ingroup  gpio_interface_gr
  * @{
  */
  
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

  
/** @defgroup GPIO_LL_Interrupt GPIO LL Interrupt Handle function
  * @ingroup  GPIO_LL_Driver
  * @brief    GPIO LL Interrupt Handle function
  * @{
  */



/**
  * @}
  */

/** @defgroup GPIO_LL_Inti_Cfg GPIO LL Initialization And Configuration
  * @ingroup  GPIO_LL_Driver
  * @brief    GPIO LL Initialization And Configuration
  * @{
  */

/** 
  * @brief  Set the DIR value.
  * @param  p_gpio: where x can be (A..D) to select the GPIO peripheral.
  * @param  gpio_initstruct: gpio ll cfg instruct. 
  * @param  dir: The dir to be set.
  * @retval None.
  */
void ll_gpio_init(GPIO_TypeDef* p_gpio, TYPE_LL_GPIO_INIT* gpio_initstruct)
{
    u32 pinpos = 0x00, pos = 0x00 , currentpin = 0x00 , wlm = 0x00;

    /*-------------------------- Configure the port pins -----------------------*/
    /*-- GPIO Mode Configuration --*/
    for(pinpos = 0x00; pinpos < 0x10; pinpos++)
    {
        pos = ((u32)0x01) << pinpos;
        /* Get the port pins position */
        currentpin = (gpio_initstruct->gpio_pin) & pos;
        if(currentpin == pos)
        {
            if((gpio_initstruct->gpio_mode == LL_GPIO_MODE_OUT) || (gpio_initstruct->gpio_mode == LL_GPIO_MODE_AF))
            {
                /* Speed OSPEEDL configuration */
                if(pinpos < 0x08)
                {
                    p_gpio->OSPEEDL &= ~(LL_GPIO_OSPEEDER_OSPEEDR0 << (pinpos * 4));
                    if(p_gpio == GPIOA)
                    {
                        if(LL_GPIO_SPEED_MODE_V == (gpio_initstruct->gpio_speed_mode))
                        {
                            p_gpio->OSPEEDL |= ((u32)(gpio_initstruct->gpio_speed_level & 0x0F) << (pinpos * 4));
                        }
                        else
                        {
                            p_gpio->OSPEEDL |= ((u32)(((gpio_initstruct->gpio_speed_level) | 0x08) & 0x0F) << (pinpos * 4));
                        }
                    }
                    else
                    {
                        if((gpio_initstruct->gpio_speed_level) == LL_GPIO_SPEED_LEVEL_2)
                        {
                            p_gpio->OSPEEDL |= ((u32)(((gpio_initstruct->gpio_speed_level) | 0x08) & 0x0F) << (pinpos * 4));
                        }
                        else if((gpio_initstruct->gpio_speed_level) > LL_GPIO_SPEED_LEVEL_2)
                        {
                            p_gpio->OSPEEDL |= ((u32)(((gpio_initstruct->gpio_speed_level) | 0x09) & 0x0F) << (pinpos * 4));
                        }
                        else
                        {
                            p_gpio->OSPEEDL |= ((u32)(gpio_initstruct->gpio_speed_level & 0x0F) << (pinpos * 4));
                        }
                    }
                }
                /* Speed OSPEEDH configuration */
                else
                {
                    wlm = pinpos - 0x08;
                    p_gpio->OSPEEDH &= ~(LL_GPIO_OSPEEDER_OSPEEDR0 << (wlm * 4));
                    if(p_gpio == GPIOA)
                    {
                        if(LL_GPIO_SPEED_MODE_V == (gpio_initstruct->gpio_speed_mode))
                        {
                            p_gpio->OSPEEDH |= ((u32)(gpio_initstruct->gpio_speed_level & 0x0F) << (wlm * 4));
                        }
                        else
                        {
                            p_gpio->OSPEEDH |= ((u32)(((gpio_initstruct->gpio_speed_level) | 0x08) & 0x0F) << (wlm * 4));
                        }
                    }
                    else
                    {
                        if((gpio_initstruct->gpio_speed_level) == LL_GPIO_SPEED_LEVEL_2)
                        {
                            p_gpio->OSPEEDH |= ((u32)(((gpio_initstruct->gpio_speed_level) | 0x08) & 0x0F) << (wlm * 4));
                        }
                        else if((gpio_initstruct->gpio_speed_level) > LL_GPIO_SPEED_LEVEL_2)
                        {
                            p_gpio->OSPEEDH |= ((u32)(((gpio_initstruct->gpio_speed_level) | 0x09) & 0x0F) << (wlm * 4));
                        }
                        else
                        {
                            p_gpio->OSPEEDH |= ((u32)(gpio_initstruct->gpio_speed_level & 0x0F) << (wlm * 4));
                        }
                    }
                }
                /* Output OTYPE configuration */
                p_gpio->OTYPE &= ~((LL_GPIO_OTYPER_OT_0) << pinpos);
                p_gpio->OTYPE |= (u16)(((u16)gpio_initstruct->gpio_type & 0x01) << pinpos);
            }

            p_gpio->MODE  &= ~(LL_GPIO_MODER_MODER0 << (pinpos * 2));

            p_gpio->MODE |= (((u32)(gpio_initstruct->gpio_mode & 0x03)) << (pinpos * 2));

            /* Pull-up Pull down resistor configuration */
            if(gpio_initstruct->gpio_pupd == LL_GPIO_PUPD_UP)
            {
                p_gpio->PUPD &= ~(LL_GPIO_PUPDR_PUPDR8 << pinpos);
                p_gpio->PUPD |= (LL_GPIO_PUPDR_PUPDR0 << pinpos);
            }else if(gpio_initstruct->gpio_pupd == LL_GPIO_PUPD_DOWN)
            {
                p_gpio->PUPD &= ~(LL_GPIO_PUPDR_PUPDR0 << pinpos);
                p_gpio->PUPD |= (LL_GPIO_PUPDR_PUPDR8 << pinpos);
            }else
            {
                p_gpio->PUPD &= ~(LL_GPIO_PUPDR_PUPDR8 << pinpos);
                p_gpio->PUPD &= ~(LL_GPIO_PUPDR_PUPDR0 << pinpos);
            }
        }
    }
}

/**
  * @brief  Reads the specified input port pin.
  * @param  p_gpio: where x can be (A, B, C) to select the GPIO peripheral.
  * @retval The input port pin value.
  */
u16 ll_gpio_read_input_data(GPIO_TypeDef* p_gpio)
{
    return ((u16)p_gpio->IDAT);
}

/**
  * @brief  Reads the specified input port pin.
  * @param  p_gpio: where x can be (A, B, C) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to read.
  * @note   This parameter can be GPIO_Pin_x where x can be:(0..15) for GPIOA, 
  *         GPIOB or GPIOC,(0..2).
  * @retval The input port pin value.
  */
u8 ll_gpio_read_input_data_bit(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    u8 bitstatus = 0x00;

    if ((p_gpio->IDAT & gpio_pin) != (u32)LL_GPIO_RESET)
    {
        bitstatus = (u8)LL_GPIO_SET;
    }
    else
    {
        bitstatus = (u8)LL_GPIO_RESET;
    }
    return bitstatus;
}

/**
  * @brief  Reads the specified GPIO output data port.
  * @param  p_gpio: where x can be (A, B, C) to select the GPIO peripheral.
  * @retval GPIO output data port value.
  */
u16 ll_gpio_read_output_data(GPIO_TypeDef* p_gpio)
{
    return ((u16)p_gpio->ODAT);
}

/**
  * @brief  Read the specified output data port bit.
  * @param  p_gpio: where x can be (A, B, C) to select the GPIO peripheral.
  * @param  gpio_pin: Specifies the port bit to read.
  * @note   This parameter can be gpio_pin where x can be:(0..15) for GPIOA, 
  *         GPIOB or GPIOC,(0..2) for GPIOD and(0..3) for GPIOF.
  * @retval The output port pin value.
  */
u8 ll_gpio_read_output_data_bit(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    uint8_t bitstatus = 0x00;

    if ((p_gpio->ODAT & gpio_pin) != (u32)LL_GPIO_RESET)
    {
        bitstatus = (uint8_t)LL_GPIO_SET;
    }
    else
    {
        bitstatus = (uint8_t)LL_GPIO_RESET;
    }
    return bitstatus;
}
/**
  * @brief  Write the specified output data port bit.
  * @param  p_gpio: where x can be (A..C) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to read.
  *          This parameter can be GPIO_Pin_x where x can be (0..15).
  * @param  gpio_set_value: gpio set value.
  * @retval None.
  */
void ll_gpio_write_bit(GPIO_TypeDef* p_gpio,  u16 gpio_pin, TPYE_ENUM_LL_GPIO_BIT_ACTION gpio_set_value)
{
    if (gpio_set_value != LL_GPIO_SET)
    {
        p_gpio->BSR = (u32)gpio_pin <<16;
    }
    else
    {
        p_gpio->BSR = (u32)gpio_pin;
    }
}
/**
  * @brief  Sets the selected data port bits.
  * @param  p_gpio: where x can be (A..C) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *   This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
  * @retval None.
  */
void ll_gpio_set_bits(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{ 
    p_gpio->BSR = (u16)gpio_pin;
}
/**
  * @brief  Clears the selected data port bits.
  * @param  p_gpio: where x can be (A..C) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *   This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
  * @retval None.
  */
void ll_gpio_reset_bits(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    p_gpio->BSR = (u32)gpio_pin <<16;
}
/**
  * @brief  Reads the specified GPIO output data port.
  * @param  p_gpio: where x can be (A..C) to select the GPIO peripheral.
  * @param  gpio_set_value: gpio set value.
  * @retval None.
  */
void ll_gpio_write_data(GPIO_TypeDef* p_gpio, u32 gpio_set_value)
{
    p_gpio->ODAT = gpio_set_value;
}
/**
  * @brief  Locks GPIO Pins configuration registers.
  * @param  p_gpio: where x can be (A..C) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bit to be written.
  *   This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
  * @retval None.
  */
void ll_gpio_pin_lock_config(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    u32 tmp = 0x00010000;

    tmp |= gpio_pin;
    /* Set LCKK bit */
    p_gpio->LCK = tmp;
    /* Reset LCKK bit */
    p_gpio->LCK =  gpio_pin;
    /* Set LCKK bit */
    p_gpio->LCK = tmp;
    /* Read LCKK bit*/
    tmp = p_gpio->LCK;
    /* Read LCKK bit*/
    tmp = p_gpio->LCK;
}
/**
  * @brief  Locks GPIO Group configuration registers.
  * @param  p_gpio: where x can be (A..C) to select the GPIO peripheral.
  * @retval None.
  */
void ll_gpio_group_lock_config(GPIO_TypeDef* p_gpio)
{
    u32 tmp = 0x0001ffff;
    p_gpio->LCK = tmp;
    /*  */
    p_gpio->LCK = 0x0000ffff;
    /*  */
    p_gpio->LCK = tmp;
    /* Read LCKK bit*/
    tmp = p_gpio->LCK;
    /* Read LCKK bit*/
    tmp = p_gpio->LCK;
}

/**
  * @brief  Writes data to the specified GPIO data port.
  * @param  p_gpio: where x can be (A or C) to select the GPIO peripheral.
  * @param  gpio_pin_src: specifies the pin for the Alternate function.
  *          This parameter can be GPIO_PinSourcex where x can be (0..15).
  * @param  gpio_af: selects the pin to used as Alternate function.
  *          This parameter can be one of the following value:
  *            @arg GPIO_AF_0: WKUP, EVENTOUT, TIM15, SPI1, TIM17,MCO, SWDAT, SWCLK, TIM14,
  *                            BOOT,UART1, CEC, IR_OUT, SPI2 
  *            @arg GPIO_AF_1: UART2, CEC, Tim3, UART1, UART2,EVENTOUT, I2C1, I2C2, TIM15 
  *            @arg GPIO_AF_2: TIM2, TIM1, EVENTOUT, TIM16, TIM17
  *            @arg GPIO_AF_3: TS, I2C1, TIM15, EVENTOUT 
  *            @arg GPIO_AF_4: TIM14
  *            @arg GPIO_AF_5: TIM16, TIM17
  *            @arg GPIO_AF_6: EVENTOUT
  *            @arg GPIO_AF_7: COMP1 OUT, COMP2 OUT 
  * @note   The pin should already been configured in Alternate Function mode(AF)
  *         using GPIO_InitStruct->GPIO_MODE = GPIO_MODE_AF.
  * @note   Refer to the Alternate function mapping table in the device datasheet 
  *         for the detailed mapping of the system and peripherals'alternate 
  *         function I/O pins.
  * @retval None.
  */
void ll_gpio_pin_af_config(GPIO_TypeDef* p_gpio, u16 gpio_pin_src, u16 gpio_af)
{
    u32 temp = 0x00;
    u32 temp_2 = 0x00;

    temp = ((u32)(gpio_af) << ((u32)((u32)gpio_pin_src & (u32)0x07) * 4));
    p_gpio->AFR[gpio_pin_src >> 0x03] &= ~((u32)0xF << ((u32)((u32)gpio_pin_src & (u32)0x07) * 4));
    temp_2 = p_gpio->AFR[gpio_pin_src >> 0x03] | temp;
    p_gpio->AFR[gpio_pin_src >> 0x03] = temp_2;
}
/**
  * @brief  Config gpio irq.
  * @param  p_gpio: where x can be (A..C) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
  * @param  newstate: DISABLE or ENABLE.
  * @retval None.
  */
void ll_gpio_irq_config(GPIO_TypeDef* p_gpio, u16 gpio_pin, FunctionalState newstate)
{
    /* if(newstate == Bit_RESET){ */
    if(newstate == DISABLE) {
        p_gpio->IMK &= ~gpio_pin;
    }else{
        p_gpio->IMK |= gpio_pin;
    }
}
/**
  * @brief  Config gpio port toggle.
  * @param  p_gpio: where x can be (A..C) to select the GPIO peripheral.
  * @param  gpio_pin: specifies the port bits to be written.
  *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15). 
  * @retval None.
  */
void ll_gpio_port_toggle(GPIO_TypeDef* p_gpio, u16 gpio_pin)
{
    p_gpio->TGL = gpio_pin;
}

/**
  * @}
  */

/** @defgroup GPIO_LL_Data_Transfers GPIO LL Data transfers functions
  * @ingroup  GPIO_LL_Driver
  * @brief    GPIO LL Data transfers functions 
  * @{
  */



/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/*************************** (C) COPYRIGHT 2018 TOPSYS ***** END OF FILE *****/
